package mdt.figure;

import org.tigris.gef.base.*;
import org.tigris.gef.presentation.Fig;
import org.tigris.gef.presentation.FigEdge;
import org.tigris.gef.presentation.FigNode;
import org.tigris.gef.presentation.Handle;
import mdt.program.MDTGraphModel;
import mdt.model.IConnector;
import mdt.model.IEdgeModel;

import java.awt.*;
import java.awt.event.MouseEvent;
import java.util.Enumeration;

/**
 * Created by lambert on 2016/6/18.
 */
public class SelectionShapedEdgeResize extends SelectionResize{

	protected static final int HANDLE_DRAG_ONLY = 9;

	private FigNode sourceFig;
	private FigNode destFig;
	private FigNode startFig;

	private Rectangle initBounds;
	/**
	 * Construct a new SelectionResize for the given Fig
	 *
	 * @param f
	 */
	public SelectionShapedEdgeResize(Fig f) {
		super(f);
		initBounds = f.getBounds();
	}

	public void dragHandle(int mX, int mY, int anX, int anY, Handle hand) {
		if (hand.index == HANDLE_DRAG_ONLY) {
			Rectangle bounds = getContentBounds();
			bounds.y = initBounds.y + mY - anY;
			getContent().setBounds(bounds);
			//getContent().translate(anX - mX, anY - mY);
		} else {
			super.dragHandle(mX, mY, anX, anY, hand);
		}
		//System.err.println("old Y: " + anY + ", new Y:" + mY);
		//System.err.println("Y moved: " + (mY- anY));
	}

	public void hitHandle(Rectangle r, Handle h) {
		super.hitHandle(r, h);
		if (h.index == -1) {
			h.index = HANDLE_DRAG_ONLY;
		}
	}

	public boolean hit(Rectangle r) {
		if (getContent().hit(r))
			return true;
		Handle h = new Handle(-1);
		super.hitHandle(r, h);
		return (h.index >= 0 && h.index <= 7);
	}

	public void mousePressed(MouseEvent me) {
		final Rectangle mousePosition =
				new Rectangle(me.getX() - 5, me.getY() - 5, 10, 10);
		if (getContent().getBounds().intersects(mousePosition)) {
			// calculate the source and dest figs for to self assoc
			sourceFig =
					((FigEdge) getContent()).getSourceFigNode();
			destFig =
					((FigEdge) getContent()).getDestFigNode();

			//reset the pointIndex
			double distToSource = sourceFig.getCenter().distance(me.getPoint());
			double distToDst = destFig.getCenter().distance(me.getPoint());
			if (distToDst <= distToSource) {
				startFig = destFig;
			} else {
				startFig = sourceFig;
			}
		}

		super.mousePressed(me);
	}

	public void mouseReleased(MouseEvent me) {
		// check pre-conds
		if (me.isConsumed() || startFig == null) {
			super.mouseReleased(me);
			return;
		}

		//Set-up:
		int x = me.getX(), y = me.getY();
		// the fig that was under the mouse when it was released
		FigNode newFig = null;
		//make a nice little target area:
		Rectangle mousePoint = new Rectangle(x - 5, y - 5, 5, 5);
		// and find the Fig:
		Editor editor = Globals.curEditor();
		LayerManager lm = editor.getLayerManager();
		Layer active = lm.getActiveLayer();
		Enumeration figs = active.elementsIn(mousePoint);
		// last is the top fig.
		while (figs.hasMoreElements()) {
			Fig candidateFig = (Fig) figs.nextElement();

			if (candidateFig instanceof FigNetworkDevice
					&& candidateFig.isSelectable()) {
				newFig = (FigNetworkDevice) candidateFig;
				break;
			}

		}
		// check intermediate post-condition.
		if (newFig == null) {
			super.mouseReleased(me);
			return;
		} else if (newFig != startFig) {
			FigShapedEdge figEdge = (FigShapedEdge) getContent();
			if (!((FigShapedEdge)getContent()).isSelfEdgeEnabled()) {
				if ((startFig == sourceFig && newFig == destFig)
					|| (startFig == destFig && newFig == sourceFig)) {
					super.mouseReleased(me);
					((FigShapedEdge)getContent()).computeRoute();
					return;
				}
			}

			MDTGraphModel graphModel = (MDTGraphModel) editor.getGraphModel();
			FigNode oldFig = startFig;
			boolean isSource = startFig != destFig;

			IEdgeModel edgeModel = (IEdgeModel)figEdge.getOwner();
			IConnector oldPort = isSource ? edgeModel.getSrcConnector() : edgeModel.getDstConnector();
			IConnector newPort = (IConnector)newFig.deepHitPort(x, y);

			// delegate the re-routing to graphmodels.
			if (graphModel.canChangeConnectedPort(newPort,oldPort, edgeModel)) {
				graphModel.changeConnectedPort(newPort, oldPort, edgeModel, isSource);
			}
			Fig portFig =  ((FigNetworkDevice)newFig).getPortFig(newFig.getOwner());
			if (isSource) {
				figEdge.setPoint(0, portFig.getClosestPoint(me.getPoint()));
			} else {
				figEdge.setPoint(1, portFig.getClosestPoint(me.getPoint()));
			}
			editor.getSelectionManager().deselect(getContent());

			figEdge.determineFigNodes();
			figEdge.computeRoute();
		}
		super.mouseReleased(me);
		return;
	}
}
